#include "syntax_tree.h"
#include "semantic_analyzer.h"
#include "main_container.h"
#include "errors_warnings.h"
extern MainContainer * CompilerData;




// Gr_GpssBlock__TerminateBlock
// Gr_TerminateBlock__terminate_Expression_spSemiCol
// Gr_TerminateBlock__terminate_spSemiCol
SemanticsBlockTerminate * SemanticAnalyzer::ReadMBTerminate(SyntaxTreeNode * mbTerminateNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBTerminate");
#endif

    SemanticsBlockTerminate * sbt;

    // check production validity
    if (mbTerminateNode->Production == Gr_GpssBlock__TerminateBlock)
    {
        // <gpss_block> ~ <terminate_block>  {terminate}
        sbt = ReadMBTerminate(mbTerminateNode->Nodes->GetData(0));
    }
    else if (mbTerminateNode->Production == Gr_TerminateBlock__terminate_Expression_spSemiCol)
    {
        // <terminate_block> ~ terminate <expression> ;  {terminate}

        SyntaxTreeNode * expressionNode = mbTerminateNode->Nodes->GetData(1);
        sbt = new SemanticsBlockTerminate();
        sbt->Expression = GatherFromExpression(expressionNode);
    }
    else if	(mbTerminateNode->Production == Gr_TerminateBlock__terminate_spSemiCol)
    {
        // <terminate_block> ~ terminate ;  {terminate}
        sbt = new SemanticsBlockTerminate();
        sbt->Expression = NULL;
    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }

#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBTerminate");
#endif

    return sbt;
};



// Gr_GpssBlock__AdvanceBlock
// Gr_AdvanceBlock__advance_Expression_PlusMinusExpression_spSemiCol
SemanticsBlockAdvance * SemanticAnalyzer::ReadMBAdvance(SyntaxTreeNode * mbAdvanceNode)
{

#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBAdvance");
#endif

    SemanticsBlockAdvance * sba;

    // check production validity
    if (mbAdvanceNode->Production == Gr_GpssBlock__AdvanceBlock)
    {
        // <gpss_block> ~ <advance_block>  {advance}
        sba = ReadMBAdvance(mbAdvanceNode->Nodes->GetData(0));
    }
    else if (mbAdvanceNode->Production == Gr_AdvanceBlock__advance_Expression_PlusMinusExpression_spSemiCol)
    {
        // <advance_block> ~ advance <expression> <plus_minus_expression> ;  {advance}
        sba = new SemanticsBlockAdvance();

        SyntaxTreeNode * expressionMeanNode = mbAdvanceNode->Nodes->GetData(1);
        sba->ExpressionMean = GatherFromExpression(expressionMeanNode);

        SyntaxTreeNode * expressionDeviationNode = mbAdvanceNode->Nodes->GetData(2);
        sba->ExpressionDeviation = GatherFromExpression(expressionDeviationNode);

    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }


#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBAdvance");
#endif

    return sba;
};




// Gr_GpssBlock__EnterBlock
// Gr_EnterBlock__enter_UnitsInExpression_Expression_FormingExpression_spSemiCol
SemanticsBlockEnter * SemanticAnalyzer::ReadMBEnter(SyntaxTreeNode * mbEnterNode)
{

#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBEnter");
#endif

    SemanticsBlockEnter * sbe;

    // check production validity
    if (mbEnterNode->Production == Gr_GpssBlock__EnterBlock)
    {
        // <gpss_block> ~ <enter_block>  {enter}
        sbe = ReadMBEnter(mbEnterNode->Nodes->GetData(0));
    }
    else if (mbEnterNode->Production == Gr_EnterBlock__enter_UnitsInExpression_Expression_FormingExpression_spSemiCol)
    {
        // <enter_block> ~ enter <units_in_expression> <expression> <forming_expression> ;  {enter}
        sbe = new SemanticsBlockEnter();

        SyntaxTreeNode * expressionUnitsIn = mbEnterNode->Nodes->GetData(1);
        sbe->ExpressionUnitsIn = GatherFromExpression(expressionUnitsIn);

        SyntaxTreeNode * expression = mbEnterNode->Nodes->GetData(2);
        sbe->Expression = GatherFromExpression(expression);

        SyntaxTreeNode * expressionForming = mbEnterNode->Nodes->GetData(3);
        sbe->ExpressionForming = GatherFromExpression(expressionForming);


    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }


#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBEnter");
#endif

    return sbe;
};




// Gr_GpssBlock__LeaveBlock
// Gr_LeaveBlock__leave_UnitsFromExpression_Expression_spSemiCol
SemanticsBlockLeave * SemanticAnalyzer::ReadMBLeave(SyntaxTreeNode * mbLeaveNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBLeave");
#endif

    SemanticsBlockLeave * sbl;

    // check production validity
    if (mbLeaveNode->Production == Gr_GpssBlock__LeaveBlock)
    {
        // <gpss_block> ~ <leave_block>  {leave}
        sbl = ReadMBLeave(mbLeaveNode->Nodes->GetData(0));
    }
    else if (mbLeaveNode->Production == Gr_LeaveBlock__leave_UnitsFromExpression_Expression_spSemiCol)
    {
        // <leave_block> ~ leave <units_from_expression> <expression> ;  {leave}
        sbl = new SemanticsBlockLeave();

        SyntaxTreeNode * expressionUnitsFrom = mbLeaveNode->Nodes->GetData(1);
        sbl->ExpressionUnitsFrom = GatherFromExpression(expressionUnitsFrom);

        SyntaxTreeNode * expression = mbLeaveNode->Nodes->GetData(2);
        sbl->Expression = GatherFromExpression(expression);

    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }


#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBLeave");
#endif

    return sbl;


}; 




// Gr_GpssBlock__SeizeBlock
// Gr_SeizeBlock__seize_Expression_FormingExpression_spSemiCol
SemanticsBlockSeize * SemanticAnalyzer::ReadMBSeize(SyntaxTreeNode * mbSeizeNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBSeize");
#endif

    SemanticsBlockSeize * sbs;

    // check production validity
    if (mbSeizeNode->Production == Gr_GpssBlock__SeizeBlock)
    {
        // <gpss_block> ~ <seize_block>  {seize}
        sbs = ReadMBSeize(mbSeizeNode->Nodes->GetData(0));
    }
    else if (mbSeizeNode->Production == Gr_SeizeBlock__seize_Expression_FormingExpression_spSemiCol)
    {
        // <seize_block> ~ seize <expression> <forming_expression> ;  {seize}
        sbs = new SemanticsBlockSeize();

        SyntaxTreeNode * expression = mbSeizeNode->Nodes->GetData(1);
        sbs->Expression = GatherFromExpression(expression);

        SyntaxTreeNode * expressionForming = mbSeizeNode->Nodes->GetData(2);
        sbs->ExpressionForming = GatherFromExpression(expressionForming);

    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }


#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBSeize");
#endif

    return sbs;
};





// Gr_GpssBlock__ReleaseBlock
// Gr_ReleaseBlock__release_Expression_spSemiCol
SemanticsBlockRelease * SemanticAnalyzer::ReadMBRelease(SyntaxTreeNode * mbReleaseNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBRelease");
#endif

    SemanticsBlockRelease * sbr;

    // check production validity
    if (mbReleaseNode->Production == Gr_GpssBlock__ReleaseBlock)
    {
        // <gpss_block> ~ <release_block>  {release}
        sbr = ReadMBRelease(mbReleaseNode->Nodes->GetData(0));
    }
    else if (mbReleaseNode->Production == Gr_ReleaseBlock__release_Expression_spSemiCol)
    {
        // <release_block> ~ release <expression> ;  {release}
        sbr = new SemanticsBlockRelease();

        SyntaxTreeNode * expression = mbReleaseNode->Nodes->GetData(1);
        sbr->Expression = GatherFromExpression(expression);

    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }


#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBRelease");
#endif

    return sbr;
};




// Gr_GpssBlock__InqueueBlock
// Gr_InqueueBlock__inqueue_Expression_spSemiCol
SemanticsBlockInqueue * SemanticAnalyzer::ReadMBInqueue(SyntaxTreeNode * mbInqueueNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBInqueue");
#endif

    SemanticsBlockInqueue * sb;

    // check production validity
    if (mbInqueueNode->Production == Gr_GpssBlock__InqueueBlock)
    {
        // <gpss_block> ~ <inqueue_block>  {inqueue}
        sb = ReadMBInqueue(mbInqueueNode->Nodes->GetData(0));
    }
    else if (mbInqueueNode->Production == Gr_InqueueBlock__inqueue_Expression_spSemiCol)
    {
        // <inqueue_block> ~ inqueue <expression> ;  {inqueue}
        sb = new SemanticsBlockInqueue();

        SyntaxTreeNode * expression = mbInqueueNode->Nodes->GetData(1);
        sb->Expression = GatherFromExpression(expression);

    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }


#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBInqueue");
#endif

    return sb;
};





// Gr_GpssBlock__OutqueueBlock
// Gr_OutqueueBlock__outqueue_Expression_spSemiCol
SemanticsBlockOutqueue * SemanticAnalyzer::ReadMBOutqueue(SyntaxTreeNode * mbOutqueueNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBOutqueue");
#endif

    SemanticsBlockOutqueue * sb;

    // check production validity
    if (mbOutqueueNode->Production == Gr_GpssBlock__OutqueueBlock)
    {
        // <gpss_block> ~ <outqueue_block>  {outqueue}
        sb = ReadMBOutqueue(mbOutqueueNode->Nodes->GetData(0));
    }
    else if (mbOutqueueNode->Production == Gr_OutqueueBlock__outqueue_Expression_spSemiCol)
    {
        // <outqueue_block> ~ outqueue <expression> ;  {outqueue}
        sb = new SemanticsBlockOutqueue();

        SyntaxTreeNode * expression = mbOutqueueNode->Nodes->GetData(1);
        sb->Expression = GatherFromExpression(expression);

    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }


#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBOutqueue");
#endif

    return sb;
}; 





// Gr_GpssBlock__ArriveBlock
// Gr_ArriveBlock__arrive_Expression_spSemiCol
SemanticsBlockArrive * SemanticAnalyzer::ReadMBArrive(SyntaxTreeNode * mbArriveNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBArrive");
#endif

    SemanticsBlockArrive * sb;

    // check production validity
    if (mbArriveNode->Production == Gr_GpssBlock__ArriveBlock)
    {
        // <gpss_block> ~ <arrive_block>  {arrive}
        sb = ReadMBArrive(mbArriveNode->Nodes->GetData(0));
    }
    else if (mbArriveNode->Production == Gr_ArriveBlock__arrive_Expression_spSemiCol)
    {
        // <arrive_block> ~ arrive <expression> ;  {arrive}
        sb = new SemanticsBlockArrive();

        SyntaxTreeNode * expression = mbArriveNode->Nodes->GetData(1);
        sb->Expression = GatherFromExpression(expression);

    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }


#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBArrive");
#endif

    return sb;
};




// Gr_GpssBlock__DepartBlock
// Gr_DepartBlock__depart_Expression_spSemiCol
SemanticsBlockDepart * SemanticAnalyzer::ReadMBDepart(SyntaxTreeNode * mbDepartNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBDepart");
#endif

    SemanticsBlockDepart * sb;

    // check production validity
    if (mbDepartNode->Production == Gr_GpssBlock__DepartBlock)
    {
        // <gpss_block> ~ <depart_block>  {depart}
        sb = ReadMBDepart(mbDepartNode->Nodes->GetData(0));
    }
    else if (mbDepartNode->Production == Gr_DepartBlock__depart_Expression_spSemiCol)
    {
        // <depart_block> ~ depart <expression> ;  {depart}
        sb = new SemanticsBlockDepart();

        SyntaxTreeNode * expression = mbDepartNode->Nodes->GetData(1);
        sb->Expression = GatherFromExpression(expression);

    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }


#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBDepart");
#endif

    return sb;

};




// Gr_GpssBlock__ModelInstanceBlock
// Gr_ModelInstanceBlock__model_Name_spLPar_Arguments_spRPar
// Gr_ModelInstanceBlock__Name_spLPar_Arguments_spRPar
SemanticsBlockModelInstance * SemanticAnalyzer::ReadMBModelInstance(SyntaxTreeNode * mbModelInstanceNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBModelInstance");
#endif

    SemanticsBlockModelInstance * sb;

    // check production validity
    if (mbModelInstanceNode->Production == Gr_GpssBlock__ModelInstanceBlock)
    {
        // <gpss_block> ~ <model_instance_block>  {model, NAME}
        sb = ReadMBModelInstance(mbModelInstanceNode->Nodes->GetData(0));
    }
	else if (mbModelInstanceNode->Production == Gr_ModelInstanceBlock__model_Name_spLPar_Arguments_spRPar_spSemiCol)
    {
        // <model_instance_block> ~ model <name> ( <arguments> )  {model}
        sb = new SemanticsBlockModelInstance();

        SyntaxTreeNode * name = mbModelInstanceNode->Nodes->GetData(1);
        delete sb->Name;
        sb->Name = GatherFromNameNode(name);

        SyntaxTreeNode * arguments = mbModelInstanceNode->Nodes->GetData(3);
        // <arguments> ~ <expression> <arguments_add>
        // <arguments> ~ ?
        if (arguments->Production != Gr_Arguments__epsilon)
        {

            // add the initial parameter
            // <arguments> ~ <expression> <arguments_add>
            SyntaxTreeNode * expression = arguments->Nodes->GetData(0);
            sb->Arguments->Add(GatherFromExpression(expression));

            // loop untill there are no more parameters
            // <arguments_add> ~ <argument_comma_add> <arguments_add>
            // <arguments_add> ~ ?
            // <argument_comma_add> ~ , <expression>
            SyntaxTreeNode * arguments_add = arguments->Nodes->GetData(1);
            while (arguments_add->Production != Gr_ArgumentsAdd__epsilon)
            {
                // <arguments_add> ~ <argument_comma_add> <arguments_add>
                // <argument_comma_add> ~ , <expression>
                SyntaxTreeNode * argument_comma_add = arguments_add->Nodes->GetData(0);
                expression = argument_comma_add->Nodes->GetData(1);
                
                sb->Arguments->Add(GatherFromExpression(expression));


                arguments_add = arguments_add->Nodes->GetData(1);
            } 
              
        }
        
    }
    else if (mbModelInstanceNode->Production == Gr_ModelInstanceBlock__Name_spLPar_Arguments_spRPar_spSemiCol)
    {
        // <model_instance_block> ~ <name> ( <arguments> )  {NAME}
        sb = new SemanticsBlockModelInstance();

        SyntaxTreeNode * name = mbModelInstanceNode->Nodes->GetData(0);
        delete sb->Name;
        sb->Name = GatherFromNameNode(name);

        SyntaxTreeNode * arguments = mbModelInstanceNode->Nodes->GetData(2);
        // <arguments> ~ <expression> <arguments_add>
        // <arguments> ~ ?
        if (arguments->Production != Gr_Arguments__epsilon)
        {

            // add the initial parameter
            // <arguments> ~ <expression> <arguments_add>
            SyntaxTreeNode * expression = arguments->Nodes->GetData(0);
            sb->Arguments->Add(GatherFromExpression(expression));

            // loop untill there are no more parameters
            // <arguments_add> ~ <argument_comma_add> <arguments_add>
            // <arguments_add> ~ ?
            // <argument_comma_add> ~ , <expression>
            SyntaxTreeNode * arguments_add = arguments->Nodes->GetData(1);
            while (arguments_add->Production != Gr_ArgumentsAdd__epsilon)
            {
                // <arguments_add> ~ <argument_comma_add> <arguments_add>
                // <argument_comma_add> ~ , <expression>
                SyntaxTreeNode * argument_comma_add = arguments_add->Nodes->GetData(0);
                expression = argument_comma_add->Nodes->GetData(1);
                
                sb->Arguments->Add(GatherFromExpression(expression));


                arguments_add = arguments_add->Nodes->GetData(1);
            } 
              
        }


    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }


#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBModelInstance");
#endif

    return sb;

};




// Gr_GpssBlock__GotoBlock
// Gr_GotoBlock__goto_Name_spSemiCol
SemanticsBlockGoto * SemanticAnalyzer::ReadMBGoto(SyntaxTreeNode * mbGotoNode)
{

#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBGoto");
#endif

    SemanticsBlockGoto * sb;

    // check production validity
    if (mbGotoNode->Production == Gr_GpssBlock__GotoBlock)
    {
        // <gpss_block> ~ <goto_block>  {goto}
        sb = ReadMBGoto(mbGotoNode->Nodes->GetData(0));
    }
    else if (mbGotoNode->Production == Gr_GotoBlock__goto_Name_spSemiCol)
    {
        // <goto_block> ~ goto <name> ;  {goto}
        sb = new SemanticsBlockGoto();

        SyntaxTreeNode * name = mbGotoNode->Nodes->GetData(1);
        delete sb->Label;
        sb->Label = GatherFromNameNode(name);

    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }


#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBGoto");
#endif

    return sb;
};




// Gr_GpssBlock__IfBlock
// Gr_IfBlock__if_spLPar_Expression_spRPar_spLCBrac_ModelStructure_spRCBrac_ElseStructure
SemanticsBlockIf * SemanticAnalyzer::ReadMBIf(SyntaxTreeNode * mbIfNode, int parentContext)
{

#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBIf");
#endif

    SemanticsBlockIf * sb;

    // check production validity
    if (mbIfNode->Production == Gr_GpssBlock__IfBlock)
    {
        // <gpss_block> ~ <if_block>  {if}
        sb = ReadMBIf(mbIfNode->Nodes->GetData(0), parentContext);
    }
    else if (mbIfNode->Production == Gr_IfBlock__if_spLPar_Expression_spRPar_spLCBrac_ModelStructure_spRCBrac_ElseStructure)
    {
        // <if_block> ~ if ( <expression> ) { <model_structure> } <else_structure>  {if}
        sb = new SemanticsBlockIf();

        SyntaxTreeNode * expression = mbIfNode->Nodes->GetData(2);
        sb->Expression = GatherFromExpression(expression);

        SyntaxTreeNode * modelStructure = mbIfNode->Nodes->GetData(5);
        sb->StructureIf = GatherFromModelStructure(modelStructure, parentContext);

        SyntaxTreeNode * elseStructure = mbIfNode->Nodes->GetData(7);
        sb->StructureElse = GatherFromModelStructure(elseStructure, parentContext);


    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }


#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBIf");
#endif

    return sb;
};



/*
SemanticsModelName * SemanticAnalyzer::ReadMBModelName(SyntaxTreeNode * mbModelNameNode); // ne zasada...
*/




// Gr_GpssBlock__WaitBlock
// Gr_WaitBlock__wait_FormingExpression_OnSensitivityList_WhileUntil_spLPar_Expression_spRPar_ThenStructure_ElseStructure_Timeout_spSemiCol
SemanticsBlockWait * SemanticAnalyzer::ReadMBWait(SyntaxTreeNode * mbWaitNode, int parentContext)
{

#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBWait");
#endif

    SemanticsBlockWait * sb;

    // check production validity
    if (mbWaitNode->Production == Gr_GpssBlock__WaitBlock)
    {
        // <gpss_block> ~ <wait_block>  {wait}
        sb = ReadMBWait(mbWaitNode->Nodes->GetData(0), parentContext);
    }
    else if (mbWaitNode->Production == Gr_WaitBlock__wait_OnSensitivityList_FormingExpression_WhileUntil_spLPar_Expression_spRPar_ThenStructure_ElseStructure_Timeout_spSemiCol)
    {
        // <wait_block> ~ wait <forming_expression> <on_sensitivity_list> <while_until> ( <expression> ) <then_structure> <else_structure> <timeout> ;  {wait}
        sb = new SemanticsBlockWait();

        SyntaxTreeNode * forming_expression = mbWaitNode->Nodes->GetData(1);
        sb->ExpressionForming = GatherFromExpression(forming_expression);


        // <on_sensitivity_list> ~ on <sensitivity_list>  {on}
        // <on_sensitivity_list> ~ ? {forming, while, until}

		// PROMJENA SINTAKSE!!!!   'forming' je dodan


        SyntaxTreeNode * on_sensitivity_list = mbWaitNode->Nodes->GetData(2);
        if (on_sensitivity_list->Production != Gr_OnSensitivityList__epsilon)
        {
            // <on_sensitivity_list> ~ on <sensitivity_list>
            SyntaxTreeNode * sensitivity_list = mbWaitNode->Nodes->GetData(1);

            SemanticsModelName * smn = new SemanticsModelName();
            
            // copy table content
            SyntaxTreeNode * name_node = sensitivity_list->Nodes->GetData(0);
            delete smn->Name;
            smn->Name = GatherFromNameNode(name_node);
            

            sb->SensitivityList->Add(smn);

            // <sensitivity_list_adds> ~ <sensitivity_list_add> <sensitivity_list_adds>
            // <sensitivity_list_adds> ~ ? 
            SyntaxTreeNode * sensitivity_list_adds = mbWaitNode->Nodes->GetData(1);
            while (sensitivity_list->Production != Gr_SensitivityListAdds__epsilon)
            {

                SyntaxTreeNode * sensitivity_list_add = sensitivity_list_adds->Nodes->GetData(0);
                SemanticsModelName * smn = new SemanticsModelName();

                // <sensitivity_list_add> ~ , <name>
                SyntaxTreeNode * name_node = sensitivity_list_add->Nodes->GetData(1);
                delete smn->Name;
                smn->Name = GatherFromNameNode(name_node);

                sb->SensitivityList->Add(smn);


                // <sensitivity_list_adds> ~ <sensitivity_list_add> <sensitivity_list_adds>
                sensitivity_list_adds = sensitivity_list_adds->Nodes->GetData(1);
            }
        }


        // find out the type of the production (while or until)
        SyntaxTreeNode * while_until = mbWaitNode->Nodes->GetData(3);
        SyntaxTreeNode * whileUntilNode = while_until->Nodes->GetData(0);
        if (whileUntilNode->Production == Gr_Terminal)
        {
            LexicUnit whileUntilLexicUnit = CompilerData->Units->GetLexicUnit(whileUntilNode->LexUnitID);
            if ((whileUntilLexicUnit.type == LUTypeKeyword) && (whileUntilLexicUnit.subtype == KeywordWhile))
                sb->Type = WaitWhile;
            else if ((whileUntilLexicUnit.type == LUTypeKeyword) && (whileUntilLexicUnit.subtype == KeywordUntil))
                sb->Type = WaitUntil;
            else
            {
                // ERROR
                // LOGIC RECOVERY
            }

        }
        else
        {
            // ERROR
            // LOGIC RECOVERY
        }

        // while until expression
        SyntaxTreeNode * expression = mbWaitNode->Nodes->GetData(5);
        sb->ExpressionWhileUntil = GatherFromExpression(expression);

        // then structure
        SyntaxTreeNode * then_structure = mbWaitNode->Nodes->GetData(7);
        sb->StructureThen = GatherFromModelStructure(then_structure, parentContext);

        // else structure
        SyntaxTreeNode * else_structure = mbWaitNode->Nodes->GetData(8);
        sb->StructureElse = GatherFromModelStructure(else_structure, parentContext);

        // timeout
        SyntaxTreeNode * timeout = mbWaitNode->Nodes->GetData(9);
        if (timeout->Production != Gr_Timeout__epsilon)
        {
            if (timeout->Production == Gr_Timeout__timeout_Expression)
            {
                // <timeout> ~ timeout <expression>
                SyntaxTreeNode * timeoutExpression = timeout->Nodes->GetData(1);
                sb->ExpressionTimeout = GatherFromExpression(timeoutExpression);
                sb->StructureTimeout = NULL;
            }
            else if (timeout->Production == Gr_Timeout__timeout_Expression_spLCBrac_ModelStructure_spRCBrac)
            {
                // <timeout> ~ timeout <expression> { <model_structure> }
                SyntaxTreeNode * timeoutExpression = timeout->Nodes->GetData(1);
                SyntaxTreeNode * modelStructure = timeout->Nodes->GetData(3);
                sb->ExpressionTimeout = GatherFromExpression(timeoutExpression);
                sb->StructureTimeout = GatherFromModelStructure(modelStructure, parentContext);
            }
        }
        else
        {
            sb->ExpressionTimeout = NULL;
            sb->StructureTimeout = NULL;
        }


    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }


#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBWait");
#endif

    return sb;
};





// Gr_GpssBlock__JoinGroupBlock
// Gr_JoinGroupBlock__join_group_Expression_spSemiCol
SemanticsBlockJoinGroup * SemanticAnalyzer::ReadMBJoinGroup(SyntaxTreeNode * mbJoinGroupNode)
{

#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBJoinGroup");
#endif

    SemanticsBlockJoinGroup * sb;

    // check production validity
    if (mbJoinGroupNode->Production == Gr_GpssBlock__JoinGroupBlock)
    {
        // <gpss_block> ~ <join_group_block>  {join}
        sb = ReadMBJoinGroup(mbJoinGroupNode->Nodes->GetData(0));
    }
    else if (mbJoinGroupNode->Production == Gr_JoinGroupBlock__join_group_Expression_spSemiCol)
    {
        // <join_group_block> ~ join group <expression> ;  {join}
        sb = new SemanticsBlockJoinGroup();

        SyntaxTreeNode * expression = mbJoinGroupNode->Nodes->GetData(2);
        sb->Expression = GatherFromExpression(expression);

    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }


#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBJoinGroup");
#endif

    return sb;
}; 





// Gr_GpssBlock__LeaveGroupBlock
// Gr_LeaveGroupBlock__leave_group_Expression_spSemiCol
SemanticsBlockLeaveGroup * SemanticAnalyzer::ReadMBLeaveGroup(SyntaxTreeNode * mbLeaveGroupNode)
{

#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBLeaveGroup");
#endif

    SemanticsBlockLeaveGroup * sb;

    // check production validity
    if (mbLeaveGroupNode->Production == Gr_GpssBlock__LeaveGroupBlock)
    {
        // <gpss_block> ~ <leave_group_block>  {leave}
        sb = ReadMBLeaveGroup(mbLeaveGroupNode->Nodes->GetData(0));
    }
    else if (mbLeaveGroupNode->Production == Gr_LeaveGroupBlock__leave_group_Expression_spSemiCol)
    {
        // <leave_group_block> ~ leave group <expression> ;  {leave}
        sb = new SemanticsBlockLeaveGroup();

        SyntaxTreeNode * expression = mbLeaveGroupNode->Nodes->GetData(2);
        sb->Expression = GatherFromExpression(expression);

    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }


#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBLeaveGroup");
#endif

    return sb;
};





// Gr_GpssBlock__GatherBlock
// Gr_GatherBlock__gather_AndDestroy_Expression_spSemiCol
// Gr_GatherBlock__gather_AndDestroy_spSemiCol
SemanticsBlockGather * SemanticAnalyzer::ReadMBGather(SyntaxTreeNode * mbGatherNode)
{

#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBGather");
#endif

    SemanticsBlockGather * sb;

    // check production validity
    if (mbGatherNode->Production == Gr_GpssBlock__GatherBlock)
    {
        // <gpss_block> ~ <gather_block>  {gather}
        sb = ReadMBGather(mbGatherNode->Nodes->GetData(0));
    }
    else if (mbGatherNode->Production == Gr_GatherBlock__gather_AndDestroy_Expression_spSemiCol)
    {
        // <gather_block> ~ gather <and_destroy> <expression> ;  {gather}
        sb = new SemanticsBlockGather();

        SyntaxTreeNode * and_destroy = mbGatherNode->Nodes->GetData(1);
        if (and_destroy->Production == Gr_AndDestroy__and_destroy)
        {
            sb->Destroy = true;
        }
        else if (and_destroy->Production == Gr_AndDestroy__epsilon)
        {
            sb->Destroy = true;
        }
        
        SyntaxTreeNode * expression = mbGatherNode->Nodes->GetData(2);
        sb->Expression = GatherFromExpression(expression);

    }
    else if (mbGatherNode->Production == Gr_GatherBlock__gather_AndDestroy_spSemiCol)
    {
        // <gather_block> ~ gather <and_destroy> ;  {gather}
        sb = new SemanticsBlockGather();

        SyntaxTreeNode * and_destroy = mbGatherNode->Nodes->GetData(1);
        if (and_destroy->Production == Gr_AndDestroy__and_destroy)
        {
            sb->Destroy = true;
        }
        else if (and_destroy->Production == Gr_AndDestroy__epsilon)
        {
            sb->Destroy = true;
        } 


        sb->Expression = NULL;

    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }


#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBGather");
#endif

    return sb;
}; 





// Gr_GpssBlock__ExecuteBlock
// Gr_ExecuteBlock__execute_spLCBrac_MethodBody_spRCBrac
// Gr_ExecuteBlock__exec_spLCBrac_MethodBody_spRCBrac
SemanticsBlockExecute * SemanticAnalyzer::ReadMBExecuter(SyntaxTreeNode * mbExecuteNode)
{

#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBExecuter");
#endif

    SemanticsBlockExecute * sb;

    // check production validity
    if (mbExecuteNode->Production == Gr_GpssBlock__ExecuteBlock)
    {
        // <gpss_block> ~ <execute_block>  {execute, exec}
        sb = ReadMBExecuter(mbExecuteNode->Nodes->GetData(0));
    }
    else if (mbExecuteNode->Production == Gr_ExecuteBlock__execute_spLCBrac_MethodBody_spRCBrac)
    {
        // <execute_block> ~ execute { <method_body> }  {execute}
        sb = new SemanticsBlockExecute();

        SyntaxTreeNode * method_body = mbExecuteNode->Nodes->GetData(2);
        sb->Body = ReadMethodBody(method_body);

    }
    else if (mbExecuteNode->Production == Gr_ExecuteBlock__exec_spLCBrac_MethodBody_spRCBrac)
    {
        // <execute_block> ~ exec { <method_body> }  {exec}
        sb = new SemanticsBlockExecute();

        SyntaxTreeNode * method_body = mbExecuteNode->Nodes->GetData(2);
        sb->Body = ReadMethodBody(method_body);

    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }


#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBExecuter");
#endif

    return sb;
}; 
